home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Video
/
World of Video.iso
/
gfxprograms
/
3dprograms
/
t3dlib
/
source
/
merge.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-13
|
5KB
|
200 lines
/* merge.c - optimize an object by removing common points and edges
* - Written by Glenn M. Lewis - 3/10/92
*/
#include <stdio.h>
#include "t3dlib.h"
#ifdef __STDC__
#include <stdlib.h>
#include <strings.h>
#include "merge_protos.h"
#endif
static char rcs_id[] = "$Id: merge.c,v 1.10 1993/01/30 23:43:03 glewis Exp $";
void merge_object();
void merge_World(world)
WORLD *world;
{
OBJECT *o;
for (o=world->object; o; o=o->next)
merge_object(o);
}
void remove_point(desc, p)
register DESC *desc;
int p;
{
register UWORD *e;
register int i;
if (p >= desc->pcount-1) { /* No need to do anything */
desc->pcount--;
return;
}
/* First, move all the points closer to the front of the list */
bcopy((char*)&desc->pnts[p+1], (char*)&desc->pnts[p],
(unsigned)(desc->pcount-p-1)*sizeof(XYZ_st));
desc->pcount--;
/* Next, decrement all Point indices that are equal to or greater than "p" */
for (i=desc->ecount,e=desc->edge; i--; e+=2) {
if (e[0] >= p) e[0]--;
if (e[1] >= p) e[1]--;
}
}
void remove_edge(desc, e)
register DESC *desc;
int e;
{
register UWORD *f;
register int i;
if (e >= desc->ecount-1) { /* No need to do anything */
desc->ecount--;
return;
}
/* First, move all the edges closer to the front of the list */
bcopy((char*)&desc->edge[(e+1)<<1], (char*)&desc->edge[e<<1],
(unsigned)(desc->ecount-e-1)*2*sizeof(UWORD));
desc->ecount--;
/* Next, decrement all Edge indices that are equal to or greater than "e" */
for (i=desc->fcount,f=desc->face; i--; f+=3) {
if (f[0] >= e) f[0]--;
if (f[1] >= e) f[1]--;
if (f[2] >= e) f[2]--;
}
}
void merge_points(desc, p1, p2)
register DESC *desc;
int p1, p2;
{
register UWORD *e;
register int i;
/* First, check all edges, and those that point to "p2" make point to "p1" */
for (e=desc->edge,i=0; i<desc->ecount; i++,e+=2) {
if (e[0] == p2) e[0] = p1;
if (e[1] == p2) e[1] = p1;
/* If the two points in the edge are the same point, remove the edge! */
if (e[0] == e[1]) { remove_edge(desc, i); i--; e-=2; }
}
/* Next, remove the duplicate point and adjust *all* the pointers */
remove_point(desc, p2);
}
void merge_edges(desc, e1, e2)
register DESC *desc;
int e1, e2;
{
register UWORD *f;
register int i;
/* First, check all faces, and those that point to "e2" make point to "e1" */
for (f=desc->face,i=0; i<desc->fcount; i++,f+=3) {
if (f[0] == e2) f[0] = e1;
if (f[1] == e2) f[1] = e1;
if (f[2] == e2) f[2] = e1;
}
/* Next, remove the duplicate edge and adjust *all* the pointers */
remove_edge(desc, e2);
}
void merge_object(obj)
OBJECT *obj;
{
register DESC *desc;
XYZ_st *p1, *p2;
UWORD *e1, *e2;
register int i, j;
if (obj->child) merge_object(obj->child);
if (!(desc = obj->desc) || !desc->pcount || !desc->ecount) return;
/* Merge duplicate points */
/* DO NOT ATTEMPT TO OPTIMIZE THE LOOPS, AS THE VARIABLE REFERENCES *MUST*
* BE PERFORMED EACH TIME THROUGH THE LOOP SINCE THE STRUCTURE IS CHANGING!
*/
/* Start at end and work back */
#ifdef DEBUG
fprintf(stderr, "Removing unused edges...\n");
#endif
/* Remove unused edges */
/* Start at end and work back */
for (i=desc->ecount; i--; ) {
#ifdef DEBUG
fprintf(stderr, "i:%4d:%4d\n", i, desc->ecount);
#endif
for (j=desc->fcount; j--; ) {
if (desc->face[3*j]==i ||
desc->face[3*j+1]==i ||
desc->face[3*j+2]==i) break; /* Yup, it is used. */
}
if (j<0) /* Edge is not referenced in any face. Delete. */
remove_edge(desc, i);
}
#ifdef DEBUG
fprintf(stderr, "Removing unused points...\n");
#endif
for (i=desc->pcount; i--; ) {
#ifdef DEBUG
fprintf(stderr, "i:%4d:%4d\n", i, desc->pcount);
#endif
for (j=desc->ecount; j--; ) {
if (desc->edge[j<<1]==i ||
desc->edge[(j<<1)+1]==i) break; /* Yup, it is used. */
}
if (j<0) /* Point is not referenced in any edge. Delete. */
remove_point(desc, i);
}
#ifdef DEBUG
fprintf(stderr, "Merging duplicate edges...\n");
#endif
/* Merge duplicate edges */
/* Start at end and work back */
for (i=desc->ecount-1; i--; ) {
e1 = &desc->edge[i<<1];
#ifdef DEBUG
fprintf(stderr, "i:%4d:%4d\n", i, desc->ecount);
#endif
for (j=i+1; j<desc->ecount; j++) {
e2 = &desc->edge[j<<1];
if ((e1[0] == e2[0] && e1[1] == e2[1]) ||
(e1[0] == e2[1] && e1[1] == e2[0])) {
/* Yep, the edges are identical. Merge them. */
merge_edges(desc, i, j);
j--;
}
}
}
#ifdef DEBUG
fprintf(stderr, "Merging duplicate points...\n");
#endif
for (i=desc->pcount-1; i--; ) {
p1 = &desc->pnts[i];
#ifdef DEBUG
fprintf(stderr, "i:%4d:%4d\n", i, desc->pcount);
#endif
for (j=i+1; j<desc->pcount; j++) {
p2 = &desc->pnts[j];
if (p1->x == p2->x && p1->y == p2->y && p1->z == p2->z) {
/* Yep, the points are identical. Merge them. */
merge_points(desc, i, j);
j--;
}
}
}
}